﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using yiCommerce.Core;
using yiCommerce.Core.Domain.Payments;

namespace yiCommerce.Service.Payments
{
    public class AlipayPaymentMethod : IPaymentMethod
    {
        private IWorkContext _workContext;

        public AlipayPaymentMethod(IWorkContext workContext)
        {
            _workContext = workContext;
        }

        public ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest)
        {
            var result = new ProcessPaymentResult();
            result.NewPaymentStatus = PaymentStatus.Pending;
            return result;
        }

        public string SystemName { get { return "Alipay"; }  }
        public bool CanRePostProcessPayment()
        {
            return true;
        }


        public string Get_Http(string StrUrl, int Timeout)
        {
            string strResult = string.Empty;
            try
            {
                HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(StrUrl);
                myReq.Timeout = Timeout;
                HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
                Stream myStream = HttpWResp.GetResponseStream();
                StreamReader sr = new StreamReader(myStream, Encoding.Default);
                StringBuilder strBuilder = new StringBuilder();
                while (-1 != sr.Peek())
                {
                    strBuilder.Append(sr.ReadLine());
                }

                strResult = strBuilder.ToString();
            }
            catch (Exception exc)
            {
                strResult = "Error: " + exc.Message;
            }
            return strResult;
        }

        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //string gateway = "https://www.alipay.com/cooperate/gateway.do?";
            string service = "create_direct_pay_by_user";

            string seller_email = _workContext.AlipayPaymethodSetting.AlipaySellerEmail;
            string sign_type = "MD5";
            string key = _workContext.AlipayPaymethodSetting.AlipayKey;
            string partner =  _workContext.AlipayPaymethodSetting.AlipayPartner;
            string input_charset = "utf-8";

            string show_url = "http://www.alipay.com/";

            string out_trade_no = postProcessPaymentRequest.Trading.TradingId.ToString();

            //            string out_trade_no = postProcessPaymentRequest.Order.Id.ToString();
            string subject = string.Join(",",
                                         postProcessPaymentRequest.Trading.Orders.Select(c => c.Order.Shop.ShopName)
                                                                  .ToList());
            string body = "Order from " + subject;
            string total_fee = postProcessPaymentRequest.Trading.Orders.Sum(t => t.Order.OrderTotal)
                                                        .ToString("0.00", CultureInfo.InvariantCulture);

            string notify_url = _workContext.SystemSetting.StoreLocation + "payment/paymentalipay/Notify";
            string return_url = _workContext.SystemSetting.StoreLocation + "payment/paymentalipay/Return";

            string[] para =
                {
                    "service=" + service,
                    "partner=" + partner,
                    "seller_email=" + seller_email,
                    "out_trade_no=" + out_trade_no,
                    "subject=" + subject,
                    "body=" + body,
                    "total_fee=" + total_fee,
                    "show_url=" + show_url,
                    "payment_type=1",
                    "notify_url=" + notify_url,
                    "return_url=" + return_url,
                    "_input_charset=" + input_charset
                };

            string aliay_url = CreatUrl(
                para,
                input_charset,
                key
                );
            var post = new RemotePost();
            post.FormName = "alipaysubmit";
            post.Url = "https://www.alipay.com/cooperate/gateway.do?_input_charset=utf-8";
            post.Method = "POST";

            post.Add("service", service);
            post.Add("partner", partner);
            post.Add("seller_email", seller_email);
            post.Add("out_trade_no", out_trade_no);
            post.Add("subject", subject);
            post.Add("body", body);
            post.Add("total_fee", total_fee);
            post.Add("show_url", show_url);
            post.Add("return_url", return_url);
            post.Add("notify_url", notify_url);
            post.Add("payment_type", "1");
            post.Add("sign", aliay_url);
            post.Add("sign_type", sign_type);

            post.Post();
        }


        public string CreatUrl(string[] Para, string InputCharset, string Key)
        {
            int i;
            string[] Sortedstr = BubbleSort(Para);
            StringBuilder prestr = new StringBuilder();

            for (i = 0; i < Sortedstr.Length; i++)
            {
                if (i == Sortedstr.Length - 1)
                {
                    prestr.Append(Sortedstr[i]);

                }
                else
                {
                    prestr.Append(Sortedstr[i] + "&");
                }

            }

            prestr.Append(Key);
            string sign = GetMD5(prestr.ToString(), InputCharset);
            return sign;
        }

        public string GetMD5(string Input, string Input_charset)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(Encoding.GetEncoding(Input_charset).GetBytes(Input));
            StringBuilder sb = new StringBuilder(32);
            for (int i = 0; i < t.Length; i++)
            {
                sb.Append(t[i].ToString("x").PadLeft(2, '0'));
            }
            return sb.ToString();
        }
        public string[] BubbleSort(string[] Input)
        {
            int i, j;
            string temp;

            bool exchange;

            for (i = 0; i < Input.Length; i++)
            {
                exchange = false;

                for (j = Input.Length - 2; j >= i; j--)
                {
                    if (System.String.CompareOrdinal(Input[j + 1], Input[j]) < 0)
                    {
                        temp = Input[j + 1];
                        Input[j + 1] = Input[j];
                        Input[j] = temp;

                        exchange = true;
                    }
                }

                if (!exchange)
                {
                    break;
                }
            }
            return Input;
        }

    }
}